package com.smartfast4j.manager.modules.schedule.controller;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.smartfast4j.common.annotation.LogRecord;
import com.smartfast4j.common.bean.R;
import com.smartfast4j.manager.common.controller.ManagerBaseController;
import com.smartfast4j.manager.modules.schedule.service.ScheduleJobService;
import com.smartfast4j.pojo.schedule.ScheduleJob;
import com.smartfast4j.pojo.schedule.ScheduleJobExample;
import org.apache.commons.lang3.StringUtils;
import org.quartz.TriggerUtils;
import org.quartz.impl.triggers.CronTriggerImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
* 由代码生成器生成
*/
@RestController
@RequestMapping("/scheduleJob")
public class ScheduleJobController extends ManagerBaseController {

    @Autowired
    private ScheduleJobService scheduleJobService;

    /**
     * 定时任务列表
     * @param offset
     * @param limit
     * @param jobName
     * @return
     */
    @RequestMapping("/list")
    public R list(Integer offset, Integer limit, String jobName, String author){
        if (offset != null && limit != null) {
            //分页查询
            PageHelper.offsetPage(offset, limit);
        }
        ScheduleJobExample example = new ScheduleJobExample();
        ScheduleJobExample.Criteria criteria = example.createCriteria();
        if(StringUtils.isNotEmpty(jobName)){
            criteria.andJobNameLike("%"+jobName+"%");
        }
        if(StringUtils.isNotEmpty(author)){
            criteria.andAuthorLike("%"+author+"%");
        }
        example.setOrderByClause("create_time desc");
        //只有紧跟在 PageHelper.startPage 方法后的第一个 MyBatis 的查询(select)方法会被分页。
        List<ScheduleJob> scheduleJobList = scheduleJobService.selectByExample(example);
        PageInfo<ScheduleJob> pageInfo = new PageInfo<>(scheduleJobList);
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("total",pageInfo.getTotal());
        dataMap.put("rows", pageInfo.getList());
        //服务端分页，返回的结果必须包含total、rows两个参数。漏写或错写都会导致表格无法显示数据。
        return R.ok(dataMap);
    }

    /**
     * 添加定时任务(@RequestBody注解不能少，要不然接收到的对象的属性全是null)
     * @param scheduleJob
     * @return
     */
    @RequestMapping("/add")
    @LogRecord(operation="新增任务",remark = "新增定时任务",moduleName = "定时任务")//使用自定义的LogRecord注解记录操作日志
    public R add(@RequestBody ScheduleJob scheduleJob){
        if(StringUtils.isEmpty(scheduleJob.getJobName())){
            return R.fail("请填写定时任务名称");
        }
        if(StringUtils.isEmpty(scheduleJob.getBeanName())){
            return R.fail("请填写定时任务对应的Bean名称");
        }
        if(StringUtils.isEmpty(scheduleJob.getMethodName())){
            return R.fail("请填写定时任务要执行的方法");
        }
        if(StringUtils.isEmpty(scheduleJob.getCronExpression())){
            return R.fail("请填写定时任务执行时间");
        }
        scheduleJobService.save(scheduleJob);
        return R.ok();
    }

    /**
     * 修改定时任务
     * @param scheduleJob
     * @return
     */
    @LogRecord(operation="修改任务",remark = "修改定时任务",moduleName = "定时任务")
    @RequestMapping("/update")
    public R update(@RequestBody ScheduleJob scheduleJob){
        if(StringUtils.isEmpty(scheduleJob.getJobName())){
            return R.fail("请填写定时任务名称");
        }
        if(StringUtils.isEmpty(scheduleJob.getBeanName())){
            return R.fail("请填写定时任务对应的Bean名称");
        }
        if(StringUtils.isEmpty(scheduleJob.getMethodName())){
            return R.fail("请填写定时任务要执行的方法");
        }
        if(StringUtils.isEmpty(scheduleJob.getCronExpression())){
            return R.fail("请填写定时任务执行时间");
        }
        scheduleJobService.update(scheduleJob);
        return R.ok();
    }

    /**
     * 删除定时任务
     * @param ids 要删除的资源ID，以逗号分隔
     * @return
     */
    @LogRecord(operation="删除任务",remark = "删除定时任务",moduleName = "定时任务")
    @RequestMapping("/delete")
    public R delete(String ids){
        if(StringUtils.isEmpty(ids)){
            return R.fail("请选择要删除的定时任务");
        }
        List<Long> idList = new ArrayList<>();
        String[] idArr = ids.split(",");
        for(String id:idArr){
            idList.add(Long.parseLong(id));
        }
        //根据id删除
        scheduleJobService.delete(idList);
        return R.ok();
    }

    /**
     * 执行定时任务
     * @param ids 要执行的资源ID，以逗号分隔
     * @return
     */
    @LogRecord(operation="执行任务",remark = "执行定时任务",moduleName = "定时任务")
    @RequestMapping("/run")
    public R run(String ids){
        if(StringUtils.isEmpty(ids)){
            return R.fail("请选择要执行的定时任务");
        }
        List<Long> idList = new ArrayList<>();
        String[] idArr = ids.split(",");
        for(String id:idArr){
            idList.add(Long.parseLong(id));
        }
        scheduleJobService.run(idList);
        return R.ok();
    }

    /**
     * 暂停定时任务
     * @param ids 资源ID，以逗号分隔
     * @return
     */
    @LogRecord(operation="暂停任务",remark = "暂停定时任务",moduleName = "定时任务")
    @RequestMapping("/pause")
    public R pause(String ids){
        if(StringUtils.isEmpty(ids)){
            return R.fail("请选择要暂停的定时任务");
        }
        List<Long> idList = new ArrayList<>();
        String[] idArr = ids.split(",");
        for(String id:idArr){
            idList.add(Long.parseLong(id));
        }
        scheduleJobService.pause(idList);
        return R.ok();
    }

    /**
     * 恢复定时任务
     * @param ids 资源ID，以逗号分隔
     * @return
     */
    @LogRecord(operation="恢复任务",remark = "恢复定时任务",moduleName = "定时任务")
    @RequestMapping("/resume")
    public R resume(String ids){
        if(StringUtils.isEmpty(ids)){
            return R.fail("请选择要恢复的定时任务");
        }
        List<Long> idList = new ArrayList<>();
        String[] idArr = ids.split(",");
        for(String id:idArr){
            idList.add(Long.parseLong(id));
        }
        scheduleJobService.resume(idList);
        return R.ok();
    }

    /**
     * 根据cron表达式计算出最近n次的执行具体时间，默认是计算出最近5次
     * @param cronExpression
     * @param n
     * @return
     * @throws ParseException
     */
    @RequestMapping("/countExecuteTimes")
    public R countExecuteTimes(String cronExpression, @RequestParam(defaultValue = "4") int n) throws ParseException {
        CronTriggerImpl cronTriggerImpl = new CronTriggerImpl();
        cronTriggerImpl.setCronExpression(cronExpression);
        Calendar calendar = Calendar.getInstance();
        Date now = calendar.getTime();
        calendar.add(Calendar.MONTH, 1);// 把统计的区间段设置为从现在到1月后的今天（主要是为了方法通用考虑)
        // 这里的时间是根据corn表达式算出来的值
        List<Date> dates = TriggerUtils.computeFireTimesBetween(
                cronTriggerImpl, null, now,
                calendar.getTime());
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        List<String> dateList = new ArrayList<>();
        for (int i=0; i<dates.size();i++) {
            if(i>n){
                break;
            }
            dateList.add(dateFormat.format(dates.get(i)));
        }
        return R.ok(dateList);
    }
}
